packages = c('rgdal', 'maptools', 'raster','spatstat', 'tmap', 'sf', 'tidyverse', 'SpatialAcc') 
for (p in packages){ 
  if(!require(p, character.only = T)){ 
    install.packages(p) } 
  library(p,character.only = T) }

Singapore Planning Subzone (MP14_SUBZONE_WEB_PL)

mpsz = st_read(dsn = "data", layer = "MP14_SUBZONE_WEB_PL")

Singapore Residents by Subzone, Age Group and Sex (Gender)

population = read_csv("data/respopagsex2000to2017.csv")

Singapore Residents by Subzone, Age Group and Sex, June 2017 (Gender)

popage2017pre <- population %>%
  filter(Time == 2017) %>%
  filter(AG == "65_to_69" | AG == "70_to_74" | AG == "75_to_79" | AG == "80_to_84" | AG == "85_and_over") %>%
  group_by(SZ)

popage2017pre_added <- aggregate(Pop ~ SZ, popage2017pre, sum)

Total Number of Clinics in Singapore

clinics = read_csv("data/clinics_hcidirectory.csv")

clinics_essentials <- c("clinic_name", "address", "LAT", "LONG", "X", "Y") # remove postal code

clinics <- clinics[clinics_essentials]

Total Number of TCM Clinics in Singapore

tcm = read_csv("data/tcm_tcmboard.csv")

tcm <- tcm[!duplicated(tcm$tcm_place_name), ]
  
tcm_essentials <- c("tcm_place_name", "tcm_address", "LAT", "LONG", "X", "Y")

tcm <- tcm[tcm_essentials]

names(tcm)[names(tcm) == "tcm_place_name"] <- "clinic_name"
names(tcm)[names(tcm) == "tcm_address"] <- "address"

Combine TCM and clinics

clinics_combined <- rbind(clinics, tcm)

Number of HDB blocks per planning subzone

HDB = read_csv("data/hdb_property_information.csv")

HDB_sf <- st_as_sf(HDB, coords = c("X", "Y"), crs = st_crs(mpsz))

Residents by Age Group & Type of Dwelling, Annual

popByDwelling = read_csv("data/residents-by-age-group-and-type-of-dwelling-detailed-categories-annual.csv")

Residents by Age Group & Type of Dwelling, Annual 2017

popByDwelling2017 <- popByDwelling %>%
  filter(year == 2017) %>%
  filter(level_1 == "65-69 Years" 
         | level_1 == "85 Years & Over" 
         | level_1 == "70-74 Years" 
         | level_1 == "75-79 Years"  
         | level_1 == "80-84 Years") %>%
  group_by(level_3)

popByDwelling2017
popByDwelling2017_added <- aggregate(value ~ level_3, popByDwelling2017, sum)

No. of blocks per subzone

mpsz_HDB <- st_join(HDB_sf,mpsz)

mpsz_HDB$`1_2room_total` <- mpsz_HDB$`1room_sold` + mpsz_HDB$`2room_sold` + mpsz_HDB$`1room_rental` + mpsz_HDB$`2room_rental`

mpsz_HDB_1_2_room = aggregate(mpsz_HDB$`1_2room_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_1_2_room' = 'x') 

mpsz_HDB$`3room_total` <- mpsz_HDB$`3room_sold` + mpsz_HDB$`3room_rental` + mpsz_HDB$`other_room_rental`

mpsz_HDB_3_room_added = aggregate(mpsz_HDB$`3room_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_3_room' = 'x') 

mpsz_HDB$`4room_total` <- mpsz_HDB$`4room_sold`

mpsz_HDB_4_room_added = aggregate(mpsz_HDB$`4room_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_4_room' = 'x') 

mpsz_HDB$`5room_exec_total` <- mpsz_HDB$`5room_sold` + mpsz_HDB$`exec_sold`

mpsz_HDB_5_room_exec_added = aggregate(mpsz_HDB$`5room_exec_total`, by=list(SUBZONE=mpsz_HDB$SUBZONE_N), FUN=sum) %>%
  rename('No_of_5_room_exec' = 'x')   

mpsz_HDB_added <- left_join(mpsz_HDB_1_2_room, mpsz_HDB_3_room_added, by ='SUBZONE') %>%
  left_join(., mpsz_HDB_4_room_added, by = 'SUBZONE') %>%
  left_join(., mpsz_HDB_5_room_exec_added, by = 'SUBZONE')

mpsz_HDB_added$`total_units` <- mpsz_HDB_added$`No_of_1_2_room` + mpsz_HDB_added$`No_of_3_room` + mpsz_HDB_added$`No_of_4_room` + mpsz_HDB_added$`No_of_5_room`
total_1_2_room_units <- sum(mpsz_HDB_added$No_of_1_2_room) 
total_3_room_units <- sum(mpsz_HDB_added$No_of_3_room) 
total_4_room_units <- sum(mpsz_HDB_added$No_of_4_room) 
total_5_room_exec_units <- sum(mpsz_HDB_added$No_of_5_room_exec) 

No. of elderly per block in every subzone

total_1_2_room_units <- sum(mpsz_HDB_added$No_of_1_2_room) 
total_3_room_units <- sum(mpsz_HDB_added$No_of_3_room) 
total_4_room_units <- sum(mpsz_HDB_added$No_of_4_room) 
total_5_room_units <- sum(mpsz_HDB_added$No_of_5_room) 

mpsz_HDB$No_of_Elderly_in_block_1_2 <- ifelse(mpsz_HDB$`1_2room_total` == 0, 0, mpsz_HDB$`1_2room_total`/total_1_2_room_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 1- And 2-Room Flats"]

mpsz_HDB$No_of_Elderly_in_block_3 <- ifelse(mpsz_HDB$`3room_total` == 0, 0, mpsz_HDB$`3room_total`/total_3_room_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 3-Room Flats"] 

mpsz_HDB$No_of_Elderly_in_block_4 <- ifelse(mpsz_HDB$`4room_total` == 0, 0, mpsz_HDB$`4room_total`/total_4_room_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 4-Room Flats"]

mpsz_HDB$No_of_Elderly_in_block_5 <- ifelse(mpsz_HDB$`5room_exec_total` == 0, 0, mpsz_HDB$`5room_exec_total`/total_5_room_exec_units) * popByDwelling2017_added$value[popByDwelling2017_added$level_3=="HDB 5-Room And Executive Flats"]
                                    

mpsz_HDB$No_of_Elderly_in_block <- mpsz_HDB$No_of_Elderly_in_block_1_2 + mpsz_HDB$No_of_Elderly_in_block_3 + mpsz_HDB$No_of_Elderly_in_block_4 + mpsz_HDB$No_of_Elderly_in_block_5
mpsz_HDB$No_of_Elderly_in_block <- round(mpsz_HDB$No_of_Elderly_in_block)
clinics_combined <- st_as_sf(clinics_combined, coords = c("X", "Y"))
class(clinics_combined)
[1] "sf"         "tbl_df"     "tbl"        "data.frame"
#assign capacity of 2 per clinic
clinics_combined['capacity'] <- 2
mpsz_HDB_coords <- mpsz_HDB %>% st_coordinates() 
clinics_combined_coords <- clinics_combined %>% st_coordinates()
dm <- distance(mpsz_HDB_coords, clinics_combined_coords)
acc_hansen <- data.frame(ac(mpsz_HDB$No_of_Elderly_in_block, clinics_combined$capacity, dm, power=0.01, family="Hansen"))
colnames(acc_hansen) <- "accHansen"
acc_hansen <- tbl_df(acc_hansen)
HDB_acc <- bind_cols(mpsz_HDB, acc_hansen)
tmap_mode("view")
tm_shape(mpsz_HDB)+
  tm_symbols(size = 0.1)+
tm_shape(HDB_acc)+
tm_bubbles(col = "accHansen",
           n=5,
           style = "quantile",
           size = 0.1,
           border.col = "black",
           border.lwd = 1)
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7ciBlY2hvPVRSVUUsIGV2YWw9VFJVRSwgbWVzc2FnZT0gRkFMU0V9DQpwYWNrYWdlcyA9IGMoJ3JnZGFsJywgJ21hcHRvb2xzJywgJ3Jhc3RlcicsJ3NwYXRzdGF0JywgJ3RtYXAnLCAnc2YnLCAndGlkeXZlcnNlJywgJ1NwYXRpYWxBY2MnKSANCmZvciAocCBpbiBwYWNrYWdlcyl7IA0KICBpZighcmVxdWlyZShwLCBjaGFyYWN0ZXIub25seSA9IFQpKXsgDQogICAgaW5zdGFsbC5wYWNrYWdlcyhwKSB9IA0KICBsaWJyYXJ5KHAsY2hhcmFjdGVyLm9ubHkgPSBUKSB9DQpgYGANCg0KU2luZ2Fwb3JlIFBsYW5uaW5nIFN1YnpvbmUgKE1QMTRfU1VCWk9ORV9XRUJfUEwpDQpgYGB7cn0NCm1wc3ogPSBzdF9yZWFkKGRzbiA9ICJkYXRhIiwgbGF5ZXIgPSAiTVAxNF9TVUJaT05FX1dFQl9QTCIpDQoNCmBgYA0KDQpTaW5nYXBvcmUgUmVzaWRlbnRzIGJ5IFN1YnpvbmUsIEFnZSBHcm91cCBhbmQgU2V4IChHZW5kZXIpDQpgYGB7cn0NCnBvcHVsYXRpb24gPSByZWFkX2NzdigiZGF0YS9yZXNwb3BhZ3NleDIwMDB0bzIwMTcuY3N2IikNCg0KYGBgDQoNClNpbmdhcG9yZSBSZXNpZGVudHMgYnkgU3Viem9uZSwgQWdlIEdyb3VwIGFuZCBTZXgsIEp1bmUgMjAxNyAoR2VuZGVyKQ0KYGBge3J9DQpwb3BhZ2UyMDE3cHJlIDwtIHBvcHVsYXRpb24gJT4lDQogIGZpbHRlcihUaW1lID09IDIwMTcpICU+JQ0KICBmaWx0ZXIoQUcgPT0gIjY1X3RvXzY5IiB8IEFHID09ICI3MF90b183NCIgfCBBRyA9PSAiNzVfdG9fNzkiIHwgQUcgPT0gIjgwX3RvXzg0IiB8IEFHID09ICI4NV9hbmRfb3ZlciIpICU+JQ0KICBncm91cF9ieShTWikNCg0KcG9wYWdlMjAxN3ByZV9hZGRlZCA8LSBhZ2dyZWdhdGUoUG9wIH4gU1osIHBvcGFnZTIwMTdwcmUsIHN1bSkNCg0KYGBgDQoNCg0KVG90YWwgTnVtYmVyIG9mIENsaW5pY3MgaW4gU2luZ2Fwb3JlDQpgYGB7cn0NCmNsaW5pY3MgPSByZWFkX2NzdigiZGF0YS9jbGluaWNzX2hjaWRpcmVjdG9yeS5jc3YiKQ0KDQpjbGluaWNzX2Vzc2VudGlhbHMgPC0gYygiY2xpbmljX25hbWUiLCAiYWRkcmVzcyIsICJMQVQiLCAiTE9ORyIsICJYIiwgIlkiKSAjIHJlbW92ZSBwb3N0YWwgY29kZQ0KDQpjbGluaWNzIDwtIGNsaW5pY3NbY2xpbmljc19lc3NlbnRpYWxzXQ0KYGBgDQoNCg0KVG90YWwgTnVtYmVyIG9mIFRDTSBDbGluaWNzIGluIFNpbmdhcG9yZQ0KYGBge3J9DQp0Y20gPSByZWFkX2NzdigiZGF0YS90Y21fdGNtYm9hcmQuY3N2IikNCg0KdGNtIDwtIHRjbVshZHVwbGljYXRlZCh0Y20kdGNtX3BsYWNlX25hbWUpLCBdDQogIA0KdGNtX2Vzc2VudGlhbHMgPC0gYygidGNtX3BsYWNlX25hbWUiLCAidGNtX2FkZHJlc3MiLCAiTEFUIiwgIkxPTkciLCAiWCIsICJZIikNCg0KdGNtIDwtIHRjbVt0Y21fZXNzZW50aWFsc10NCg0KbmFtZXModGNtKVtuYW1lcyh0Y20pID09ICJ0Y21fcGxhY2VfbmFtZSJdIDwtICJjbGluaWNfbmFtZSINCm5hbWVzKHRjbSlbbmFtZXModGNtKSA9PSAidGNtX2FkZHJlc3MiXSA8LSAiYWRkcmVzcyINCmBgYA0KDQoNCkNvbWJpbmUgVENNIGFuZCBjbGluaWNzDQpgYGB7cn0NCmNsaW5pY3NfY29tYmluZWQgPC0gcmJpbmQoY2xpbmljcywgdGNtKQ0KDQpgYGANCg0KTnVtYmVyIG9mIEhEQiBibG9ja3MgcGVyIHBsYW5uaW5nIHN1YnpvbmUNCmBgYHtyfQ0KSERCID0gcmVhZF9jc3YoImRhdGEvaGRiX3Byb3BlcnR5X2luZm9ybWF0aW9uLmNzdiIpDQoNCkhEQl9zZiA8LSBzdF9hc19zZihIREIsIGNvb3JkcyA9IGMoIlgiLCAiWSIpLCBjcnMgPSBzdF9jcnMobXBzeikpDQoNCmBgYA0KDQpSZXNpZGVudHMgYnkgQWdlIEdyb3VwICYgVHlwZSBvZiBEd2VsbGluZywgQW5udWFsDQpgYGB7cn0NCnBvcEJ5RHdlbGxpbmcgPSByZWFkX2NzdigiZGF0YS9yZXNpZGVudHMtYnktYWdlLWdyb3VwLWFuZC10eXBlLW9mLWR3ZWxsaW5nLWRldGFpbGVkLWNhdGVnb3JpZXMtYW5udWFsLmNzdiIpDQoNCmBgYA0KDQpSZXNpZGVudHMgYnkgQWdlIEdyb3VwICYgVHlwZSBvZiBEd2VsbGluZywgQW5udWFsIDIwMTcNCmBgYHtyfQ0KcG9wQnlEd2VsbGluZzIwMTcgPC0gcG9wQnlEd2VsbGluZyAlPiUNCiAgZmlsdGVyKHllYXIgPT0gMjAxNykgJT4lDQogIGZpbHRlcihsZXZlbF8xID09ICI2NS02OSBZZWFycyIgDQogICAgICAgICB8IGxldmVsXzEgPT0gIjg1IFllYXJzICYgT3ZlciIgDQogICAgICAgICB8IGxldmVsXzEgPT0gIjcwLTc0IFllYXJzIiANCiAgICAgICAgIHwgbGV2ZWxfMSA9PSAiNzUtNzkgWWVhcnMiICANCiAgICAgICAgIHwgbGV2ZWxfMSA9PSAiODAtODQgWWVhcnMiKSAlPiUNCiAgZ3JvdXBfYnkobGV2ZWxfMykNCg0KcG9wQnlEd2VsbGluZzIwMTcNCnBvcEJ5RHdlbGxpbmcyMDE3X2FkZGVkIDwtIGFnZ3JlZ2F0ZSh2YWx1ZSB+IGxldmVsXzMsIHBvcEJ5RHdlbGxpbmcyMDE3LCBzdW0pDQoNCmBgYA0KDQoNCk5vLiBvZiBibG9ja3MgcGVyIHN1YnpvbmUNCmBgYHtyfQ0KbXBzel9IREIgPC0gc3Rfam9pbihIREJfc2YsbXBzeikNCg0KbXBzel9IREIkYDFfMnJvb21fdG90YWxgIDwtIG1wc3pfSERCJGAxcm9vbV9zb2xkYCArIG1wc3pfSERCJGAycm9vbV9zb2xkYCArIG1wc3pfSERCJGAxcm9vbV9yZW50YWxgICsgbXBzel9IREIkYDJyb29tX3JlbnRhbGANCg0KbXBzel9IREJfMV8yX3Jvb20gPSBhZ2dyZWdhdGUobXBzel9IREIkYDFfMnJvb21fdG90YWxgLCBieT1saXN0KFNVQlpPTkU9bXBzel9IREIkU1VCWk9ORV9OKSwgRlVOPXN1bSkgJT4lDQogIHJlbmFtZSgnTm9fb2ZfMV8yX3Jvb20nID0gJ3gnKSANCg0KbXBzel9IREIkYDNyb29tX3RvdGFsYCA8LSBtcHN6X0hEQiRgM3Jvb21fc29sZGAgKyBtcHN6X0hEQiRgM3Jvb21fcmVudGFsYCArIG1wc3pfSERCJGBvdGhlcl9yb29tX3JlbnRhbGANCg0KbXBzel9IREJfM19yb29tX2FkZGVkID0gYWdncmVnYXRlKG1wc3pfSERCJGAzcm9vbV90b3RhbGAsIGJ5PWxpc3QoU1VCWk9ORT1tcHN6X0hEQiRTVUJaT05FX04pLCBGVU49c3VtKSAlPiUNCiAgcmVuYW1lKCdOb19vZl8zX3Jvb20nID0gJ3gnKSANCg0KbXBzel9IREIkYDRyb29tX3RvdGFsYCA8LSBtcHN6X0hEQiRgNHJvb21fc29sZGANCg0KbXBzel9IREJfNF9yb29tX2FkZGVkID0gYWdncmVnYXRlKG1wc3pfSERCJGA0cm9vbV90b3RhbGAsIGJ5PWxpc3QoU1VCWk9ORT1tcHN6X0hEQiRTVUJaT05FX04pLCBGVU49c3VtKSAlPiUNCiAgcmVuYW1lKCdOb19vZl80X3Jvb20nID0gJ3gnKSANCg0KbXBzel9IREIkYDVyb29tX2V4ZWNfdG90YWxgIDwtIG1wc3pfSERCJGA1cm9vbV9zb2xkYCArIG1wc3pfSERCJGBleGVjX3NvbGRgDQoNCm1wc3pfSERCXzVfcm9vbV9leGVjX2FkZGVkID0gYWdncmVnYXRlKG1wc3pfSERCJGA1cm9vbV9leGVjX3RvdGFsYCwgYnk9bGlzdChTVUJaT05FPW1wc3pfSERCJFNVQlpPTkVfTiksIEZVTj1zdW0pICU+JQ0KICByZW5hbWUoJ05vX29mXzVfcm9vbV9leGVjJyA9ICd4JykgICANCg0KbXBzel9IREJfYWRkZWQgPC0gbGVmdF9qb2luKG1wc3pfSERCXzFfMl9yb29tLCBtcHN6X0hEQl8zX3Jvb21fYWRkZWQsIGJ5ID0nU1VCWk9ORScpICU+JQ0KICBsZWZ0X2pvaW4oLiwgbXBzel9IREJfNF9yb29tX2FkZGVkLCBieSA9ICdTVUJaT05FJykgJT4lDQogIGxlZnRfam9pbiguLCBtcHN6X0hEQl81X3Jvb21fZXhlY19hZGRlZCwgYnkgPSAnU1VCWk9ORScpDQoNCm1wc3pfSERCX2FkZGVkJGB0b3RhbF91bml0c2AgPC0gbXBzel9IREJfYWRkZWQkYE5vX29mXzFfMl9yb29tYCArIG1wc3pfSERCX2FkZGVkJGBOb19vZl8zX3Jvb21gICsgbXBzel9IREJfYWRkZWQkYE5vX29mXzRfcm9vbWAgKyBtcHN6X0hEQl9hZGRlZCRgTm9fb2ZfNV9yb29tYA0KYGBgDQoNCmBgYHtyfQ0KdG90YWxfMV8yX3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzFfMl9yb29tKSANCnRvdGFsXzNfcm9vbV91bml0cyA8LSBzdW0obXBzel9IREJfYWRkZWQkTm9fb2ZfM19yb29tKSANCnRvdGFsXzRfcm9vbV91bml0cyA8LSBzdW0obXBzel9IREJfYWRkZWQkTm9fb2ZfNF9yb29tKSANCnRvdGFsXzVfcm9vbV9leGVjX3VuaXRzIDwtIHN1bShtcHN6X0hEQl9hZGRlZCROb19vZl81X3Jvb21fZXhlYykgDQoNCmBgYA0KDQoNCk5vLiBvZiBlbGRlcmx5IHBlciBibG9jayBpbiBldmVyeSBzdWJ6b25lDQpgYGB7cn0NCnRvdGFsXzFfMl9yb29tX3VuaXRzIDwtIHN1bShtcHN6X0hEQl9hZGRlZCROb19vZl8xXzJfcm9vbSkgDQp0b3RhbF8zX3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzNfcm9vbSkgDQp0b3RhbF80X3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzRfcm9vbSkgDQp0b3RhbF81X3Jvb21fdW5pdHMgPC0gc3VtKG1wc3pfSERCX2FkZGVkJE5vX29mXzVfcm9vbSkgDQoNCm1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfMV8yIDwtIGlmZWxzZShtcHN6X0hEQiRgMV8ycm9vbV90b3RhbGAgPT0gMCwgMCwgbXBzel9IREIkYDFfMnJvb21fdG90YWxgL3RvdGFsXzFfMl9yb29tX3VuaXRzKSAqIHBvcEJ5RHdlbGxpbmcyMDE3X2FkZGVkJHZhbHVlW3BvcEJ5RHdlbGxpbmcyMDE3X2FkZGVkJGxldmVsXzM9PSJIREIgMS0gQW5kIDItUm9vbSBGbGF0cyJdDQoNCm1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfMyA8LSBpZmVsc2UobXBzel9IREIkYDNyb29tX3RvdGFsYCA9PSAwLCAwLCBtcHN6X0hEQiRgM3Jvb21fdG90YWxgL3RvdGFsXzNfcm9vbV91bml0cykgKiBwb3BCeUR3ZWxsaW5nMjAxN19hZGRlZCR2YWx1ZVtwb3BCeUR3ZWxsaW5nMjAxN19hZGRlZCRsZXZlbF8zPT0iSERCIDMtUm9vbSBGbGF0cyJdIA0KDQptcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrXzQgPC0gaWZlbHNlKG1wc3pfSERCJGA0cm9vbV90b3RhbGAgPT0gMCwgMCwgbXBzel9IREIkYDRyb29tX3RvdGFsYC90b3RhbF80X3Jvb21fdW5pdHMpICogcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkdmFsdWVbcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkbGV2ZWxfMz09IkhEQiA0LVJvb20gRmxhdHMiXQ0KDQptcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrXzUgPC0gaWZlbHNlKG1wc3pfSERCJGA1cm9vbV9leGVjX3RvdGFsYCA9PSAwLCAwLCBtcHN6X0hEQiRgNXJvb21fZXhlY190b3RhbGAvdG90YWxfNV9yb29tX2V4ZWNfdW5pdHMpICogcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkdmFsdWVbcG9wQnlEd2VsbGluZzIwMTdfYWRkZWQkbGV2ZWxfMz09IkhEQiA1LVJvb20gQW5kIEV4ZWN1dGl2ZSBGbGF0cyJdDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCg0KbXBzel9IREIkTm9fb2ZfRWxkZXJseV9pbl9ibG9jayA8LSBtcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrXzFfMiArIG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfMyArIG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfNCArIG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2tfNQ0KYGBgDQoNCg0KYGBge3J9DQptcHN6X0hEQiROb19vZl9FbGRlcmx5X2luX2Jsb2NrIDwtIHJvdW5kKG1wc3pfSERCJE5vX29mX0VsZGVybHlfaW5fYmxvY2spDQpgYGANCg0KYGBge3J9DQpjbGluaWNzX2NvbWJpbmVkIDwtIHN0X2FzX3NmKGNsaW5pY3NfY29tYmluZWQsIGNvb3JkcyA9IGMoIlgiLCAiWSIpKQ0KY2xhc3MoY2xpbmljc19jb21iaW5lZCkNCmBgYA0KDQpgYGB7cn0NCiNhc3NpZ24gY2FwYWNpdHkgb2YgMiBwZXIgY2xpbmljDQpjbGluaWNzX2NvbWJpbmVkWydjYXBhY2l0eSddIDwtIDINCmBgYA0KDQpgYGB7cn0NCm1wc3pfSERCX2Nvb3JkcyA8LSBtcHN6X0hEQiAlPiUgc3RfY29vcmRpbmF0ZXMoKSANCmNsaW5pY3NfY29tYmluZWRfY29vcmRzIDwtIGNsaW5pY3NfY29tYmluZWQgJT4lIHN0X2Nvb3JkaW5hdGVzKCkNCmBgYA0KDQpgYGB7cn0NCmRtIDwtIGRpc3RhbmNlKG1wc3pfSERCX2Nvb3JkcywgY2xpbmljc19jb21iaW5lZF9jb29yZHMpDQphY2NfaGFuc2VuIDwtIGRhdGEuZnJhbWUoYWMobXBzel9IREIkTm9fb2ZfRWxkZXJseV9pbl9ibG9jaywgY2xpbmljc19jb21iaW5lZCRjYXBhY2l0eSwgZG0sIHBvd2VyPTAuMDEsIGZhbWlseT0iSGFuc2VuIikpDQpjb2xuYW1lcyhhY2NfaGFuc2VuKSA8LSAiYWNjSGFuc2VuIg0KYWNjX2hhbnNlbiA8LSB0YmxfZGYoYWNjX2hhbnNlbikNCkhEQl9hY2MgPC0gYmluZF9jb2xzKG1wc3pfSERCLCBhY2NfaGFuc2VuKQ0KYGBgDQoNCmBgYHtyfQ0KdG1hcF9tb2RlKCJ2aWV3IikNCmBgYA0KDQpgYGB7cn0NCnRtX3NoYXBlKG1wc3pfSERCKSsNCiAgdG1fc3ltYm9scyhzaXplID0gMC4xKSsNCnRtX3NoYXBlKEhEQl9hY2MpKw0KdG1fYnViYmxlcyhjb2wgPSAiYWNjSGFuc2VuIiwNCiAgICAgICAgICAgbj01LA0KICAgICAgICAgICBzdHlsZSA9ICJxdWFudGlsZSIsDQogICAgICAgICAgIHNpemUgPSAwLjEsDQogICAgICAgICAgIGJvcmRlci5jb2wgPSAiYmxhY2siLA0KICAgICAgICAgICBib3JkZXIubHdkID0gMSkNCmBgYA==